package org.rcy.framework.data.config;

import com.zaxxer.hikari.HikariDataSource;
import org.rcy.framework.data.config.mybatis.SimulateDataSourceConfigurer;
import org.rcy.framework.data.constant.CommonConstants;
import org.rcy.framework.data.datasource.DataSourceProperties;
import org.rcy.framework.data.datasource.DataSourceChangeListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;

@EnableConfigurationProperties(DataSourceProperties.class)
@Configuration
public class DataSourceAutoConfiguration {

	@Autowired
	private DataSourceProperties properties;

	@Bean
	@Conditional(ShardingjdbcDataSourceCondition.class)
	@ConditionalOnProperty("spring.datasource.url")
	public HikariDataSource dataSource() {
		return getHikariDataSource(properties);
	}
	
	public static HikariDataSource getHikariDataSource(DataSourceProperties properties) {
		HikariDataSource ds = new HikariDataSource();
		ds.setJdbcUrl(properties.getUrl());
		ds.setUsername(properties.getUsername());
		ds.setPassword(properties.getPassword());
		ds.setMaximumPoolSize(properties.getMaxPoolSize());
		ds.setMinimumIdle(properties.getMinIdle());
		ds.setConnectionTimeout(properties.getConnectionTimeout());
		// 设置检测sql，如果已经配置，则以配置优先，默认情况下，对于oracle，需要特殊化处理
		if(StringUtils.isEmpty(ds.getConnectionTestQuery())){
			// 设定检测SQL
			if(properties.getDatabaseId().equalsIgnoreCase(CommonConstants.ORACLE_DB_ID)){
				ds.setConnectionTestQuery(CommonConstants.ORACLE_CON_TEST_SQL);
			}else{
				ds.setConnectionTestQuery(CommonConstants.DEFAULT_CON_TEST_SQL);
			}
		}else{
			ds.setConnectionTestQuery(properties.getConnectionTestQuery());
		}
		// 设置检测连接超时
		ds.setValidationTimeout(properties.getValidationTimeout());
		// 设置连接最大生存时间
		ds.setMaxLifetime(properties.getMaxLifeTime());
		//设置jmx监控
		ds.setRegisterMbeans(properties.isRegisterMbeans());

		return ds;
	}

	@Bean
	public DataSourceChangeListener dataSourceChangeListener() {
		return new DataSourceChangeListener();
	}

	@Configuration
// 	@ConditionalOnMissingBean(DataSource.class)
	@Conditional(SimulateDataSourceCondition.class)
	@Import(SimulateDataSourceConfigurer.class)
//	@Profile({"production","develop"})
	public static class SimulateDataSourceConfiguration {

	}
	
	static class SimulateDataSourceCondition extends SpringBootCondition {

		@Override
		public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
			String url = context.getEnvironment().getProperty("spring.datasource.url");
			if (StringUtils.hasText(url)) {
				return ConditionOutcome.noMatch("explicit url " + url);
			}
			return ConditionOutcome.match("No explicit url");
		}

	}
	
	static class ShardingjdbcDataSourceCondition extends SpringBootCondition {

		@Override
		public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
			String enabled = context.getEnvironment().getProperty("spring.shardingsphere.enabled","false");
			if (Boolean.valueOf(enabled).booleanValue()) {
				return ConditionOutcome.noMatch("sharding enabled");
			}
			return ConditionOutcome.match("sharding unable");
		}
		
	}
	
}